home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / iritsm3s.zip / INTERACT.C < prev    next >
C/C++ Source or Header  |  1992-02-26  |  21KB  |  642 lines

  1. /*****************************************************************************
  2. * Module to handle viewing of objects in the ViewWindow.             *
  3. *                                         *
  4. * Written by:  Gershon Elber            Unix - X11 Ver 0.1, Mar. 1990    *
  5. *****************************************************************************/
  6.  
  7. #ifdef __MSDOS__
  8. #include <conio.h>
  9. #include <graphics.h>
  10. #endif /* __MSDOS__ */
  11.  
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <setjmp.h>
  15. #include <math.h>
  16. #include "program.h"
  17. #include "interact.h"
  18. #include "iritprsr.h"
  19. #include "graphgen.h"
  20.  
  21. #ifdef SUPPORT_GIF_SAVE
  22. #include "gif_lib.h"
  23. #endif /* SUPPORT_GIF_SAVE */
  24.  
  25. #define MAX_ROTATE_ANGLE    45.0 /* Max. rates used by interactive mode. */
  26. #define MAX_TRANSLATE_FACTOR    2.0
  27. #define MAX_SCALE_FACTOR    2.0
  28. #define MAX_PERSP_FACTOR    2.0
  29. #define PERSPECTIVE_DEFAULT    -5
  30.  
  31. /* We support depth cues iff DepthCueFlag is TRUE: */
  32. #define IS_DOTTED_LINE  (GlblDepthCue ? DOTTED_LINE : SOLID_LINE)
  33.  
  34. static RealType LastCoord[3];  /* Used to store last point we moved/draw to. */
  35.  
  36. void (* MoveToPtr)(RealType Coord[3]);
  37. void (* DrawToPtr)(RealType Coord[3]);
  38.  
  39. /* Save the current displayed object information in local variables. */
  40. static IPObjectStruct *LocalObjects;
  41.  
  42. static jmp_buf LongJumpBuffer;                    /* Used in breaking. */
  43.  
  44. static void ViewGeomObjectList(IPObjectStruct *Objects);
  45. static void SaveCurrentMat(void);
  46. static void DrawOneObject(IPObjectStruct *PObject);
  47. static void DrawOnePolygon(IPPolygonStruct *PPolygon);
  48. static void TestQuitView(void);
  49. #ifdef __GL__
  50. static void DrawPolygonSolid(IPPolygonStruct *PPolygon);
  51. #endif /* __GL__ */
  52.  
  53. /*****************************************************************************
  54. *  Routine to handle data from the input device (keyboard, mouse etc.) -     *
  55. * clip it against the sub windows of the interactive menu and perform the    *
  56. * required transfomation, by updating the global view matrix object VIEW_MAT *
  57. *  The input data in the Rotation/Translation/Scaling sub windows is used    *
  58. * (horizontal distance from sub window center) to set amount of change.         *
  59. *****************************************************************************/
  60. void InteractGeomObject(IPObjectStruct *Objects)
  61. {
  62. #ifdef SUPPORT_GIF_SAVE
  63.     static char GifFileCount = '0';
  64.     char GifFileName[PATH_NAME_LEN];
  65. #endif /* SUPPORT_GIF_SAVE */
  66.     char *p;
  67.     int UpdateView;
  68.     RealType ChangeFactor;
  69.     MatrixType Mat, OrigViewMat, OrigPrspMat;
  70. #ifndef __MSDOS__
  71.     long WinID, DispID, ColorMapID;
  72. #endif /* __MSDOS__ */
  73.  
  74.     /* Save copy of original matrix, so we can recover if reset is required. */
  75.     GEN_COPY(OrigViewMat, IritPrsrViewMat, sizeof(MatrixType));
  76.     GEN_COPY(OrigPrspMat, IritPrsrPrspMat, sizeof(MatrixType));
  77.  
  78.     /* Update the drawing routine pointers: */
  79.     MoveToPtr = ScrnMoveTo;
  80.     DrawToPtr = ScrnDrawTo;
  81.  
  82.     switch (GlblViewMode) {             /* Update the current view. */
  83.     case VIEW_ORTHOGRAPHIC:
  84.         GEN_COPY(CrntViewMat, IritPrsrViewMat, sizeof(MatrixType));
  85.         break;
  86.     case VIEW_PERSPECTIVE:
  87.         MultTwo4by4(CrntViewMat, IritPrsrViewMat, IritPrsrPrspMat);
  88.         break;
  89.     }
  90.  
  91.     LocalObjects = Objects;
  92.  
  93.     GGMySetLineStyle(SOLID_LINE);
  94.  
  95.     GGClearViewArea();                   /* Clear the view window. */
  96.     ViewGeomObjectList(Objects);           /* Display it for first time. */
  97.  
  98. #if defined(__MSDOS__) || defined(DJGCC)
  99.     /* Set the async. function for intr_lib to refresh the view window. */
  100.     IntrWndwSetRefreshFunc(ViewWindowID,
  101.                (IntrIntFunc) UpdateInteractHandleInput);
  102. #endif /* __MSDOS__ || DJGCC */
  103.  
  104.     while (TRUE) {
  105.     UpdateView = TRUE;
  106.     GenUnitMat(Mat);            /* No transformation by default! */
  107.  
  108.     switch (GGGetGraphicEvent(&ChangeFactor)) {
  109.         case EVENT_SCR_OBJ_TGL:    /* Its Coordinate system - toggle it. */
  110.         UpdateView = FALSE;
  111.         break;
  112.         case EVENT_PERS_ORTHO_TGL:           /* Its View mode - toggle it. */
  113.         break;
  114.         case EVENT_PERS_ORTHO_Z: /* Its Perspective Z focal point modif. */
  115.         if (GlblViewMode != VIEW_PERSPECTIVE) {
  116.             GGTone(1000, 100);               /* Do some noise! */
  117.             UpdateView = FALSE;
  118.             break;
  119.         }
  120.         /* Make it between 0.5 and 1.5: */
  121.         ChangeFactor = ChangeFactor / 2.0 + 1.0;
  122.         IritPrsrPrspMat[2][2] *= ChangeFactor;
  123.         IritPrsrPrspMat[2][3] *= ChangeFactor;
  124.         IritPrsrPrspMat[3][2] *= ChangeFactor;
  125.         break;
  126.         case EVENT_ROTATE_X:       /* Its rotation along the X axis. */
  127.         GenMatRotX1(DEG2RAD(ChangeFactor * MAX_ROTATE_ANGLE), Mat);
  128.         break;
  129.         case EVENT_ROTATE_Y:       /* Its rotation along the Y axis. */
  130.         GenMatRotY1(DEG2RAD(ChangeFactor * MAX_ROTATE_ANGLE), Mat);
  131.         break;
  132.         case EVENT_ROTATE_Z:       /* Its rotation along the Z axis. */
  133.         GenMatRotZ1(DEG2RAD(ChangeFactor * MAX_ROTATE_ANGLE), Mat);
  134.         break;
  135.         case EVENT_TRANSLATE_X:    /* Its translation along the X axis. */
  136.         GenMatTrans(ChangeFactor * MAX_TRANSLATE_FACTOR, 0.0, 0.0,
  137.                                     Mat);
  138.         break;
  139.         case EVENT_TRANSLATE_Y:    /* Its translation along the Y axis. */
  140.         GenMatTrans(0.0, ChangeFactor * MAX_TRANSLATE_FACTOR, 0.0,
  141.                                     Mat);
  142.         break;
  143.         case EVENT_TRANSLATE_Z:    /* Its translation along the Z axis. */
  144.         GenMatTrans(0.0, 0.0, ChangeFactor * MAX_TRANSLATE_FACTOR,
  145.                                     Mat);
  146.         break;
  147.         case EVENT_SCALE:              /* Its scaling along all axes. */
  148.         if (ChangeFactor > 0.0)              /* Make it around 1... */
  149.             ChangeFactor = ChangeFactor * MAX_SCALE_FACTOR + 1.0;
  150.         else
  151.             ChangeFactor = 1.0 /
  152.             (-ChangeFactor * MAX_SCALE_FACTOR + 1.0);
  153.         GenMatScale(ChangeFactor, ChangeFactor, ChangeFactor, Mat);
  154.         break;
  155.         case EVENT_DEPTH_CUE:
  156.         if (!GlblDepthCue) GGMySetLineStyle(SOLID_LINE);
  157.         break;
  158. #ifdef __GL__
  159.         case EVENT_DRAW_SOLID:
  160.         break;
  161. #endif
  162. #if defined(__GL__) || defined(__X11__) || defined(__MSDOS__) || defined(DJGCC)
  163.         case EVENT_SAVE_GIF:
  164. #ifdef SUPPORT_GIF_SAVE
  165.         strcpy(GifFileName, GENERIC_GIF_FILE);
  166.         if ((p = strchr(GifFileName, '#')) != NULL) {
  167.             *p = GifFileCount;
  168.             if (GifFileCount++ == '9') GifFileCount = '0';
  169.         }
  170. #ifdef __GL__
  171.         if (DumpScreen2Gif(GifFileName, (int) GIF_DUMP_SGI_WINDOW,
  172.                         GetViewWindowID(), 0, 0) != 0) {
  173. #endif
  174. #ifdef __X11__
  175.         WinID = GetViewWindowID(&DispID, &ColorMapID);
  176.         if (DumpScreen2Gif(GifFileName, (int) GIF_DUMP_X_WINDOW,
  177.                     WinID, DispID, ColorMapID) != 0) {
  178. #endif
  179. #ifdef __MSDOS__
  180.         if (DumpScreen2Gif(GifFileName, GRGraphDriver, GRGraphMode, 0, 0)
  181.             != 0) {
  182. #endif
  183. #ifdef DJGCC
  184.         if (DumpScreen2Gif(GifFileName, 0, 0, GRScreenMaxX, GRScreenMaxY)
  185.             != 0) {
  186. #endif
  187.             /* Something went wrong - let the user know about it. */
  188.             GGTone(400, 300);
  189.             GGTone(100, 300);
  190.         }
  191.         else
  192.             GGTone(1000, 100);
  193.         UpdateView = FALSE;
  194. #else
  195.         GGTone(400, 300);
  196.         GGTone(100, 300);
  197. #endif /* SUPPORT_GIF_SAVE */
  198.         break;
  199. #endif /* __GL__ || __X11__ || __MSDOS__ || DJGCC */
  200.         case EVENT_SAVE_PS:
  201.         SavePostScript(Objects);
  202.         UpdateView = FALSE;
  203.         break;
  204.         case EVENT_SAVE_MATRIX:
  205.         SaveCurrentMat();
  206.         UpdateView = FALSE;
  207.         break;
  208.         case EVENT_RESET_MATRIX:
  209.         GEN_COPY(IritPrsrViewMat, OrigViewMat, sizeof(MatrixType));
  210.         GEN_COPY(IritPrsrPrspMat, OrigPrspMat, sizeof(MatrixType));
  211.         break;
  212.         case EVENT_QUIT:
  213.         LocalObjects = NULL;
  214.         return;                        /* Its Quit. */
  215.         default:
  216.         GGTone(1000, 100);               /* Do some noise! */
  217.         UpdateView = FALSE;
  218.     }
  219.  
  220.     if (UpdateView) {
  221.         GGClearViewArea();               /* Clear the view window. */
  222.  
  223.         switch (GlblTransformMode) {/* Udpate the global viewing matrix. */
  224.         case TRANS_SCREEN:
  225.             MultTwo4by4(IritPrsrViewMat, IritPrsrViewMat, Mat);
  226.             break;
  227.         case TRANS_OBJECT:
  228.             MultTwo4by4(IritPrsrViewMat, Mat, IritPrsrViewMat);
  229.             break;
  230.         }
  231.  
  232.         switch (GlblViewMode) {         /* Update the current view. */
  233.         case VIEW_ORTHOGRAPHIC:
  234.             GEN_COPY(CrntViewMat, IritPrsrViewMat, sizeof(MatrixType));
  235.             break;
  236.         case VIEW_PERSPECTIVE:
  237.             MultTwo4by4(CrntViewMat, IritPrsrViewMat, IritPrsrPrspMat);
  238.             break;
  239.         }
  240.  
  241.         ViewGeomObjectList(Objects);        /* And display it... */
  242.     }
  243.     }
  244. }
  245.  
  246. /*****************************************************************************
  247. *  Routine to update the viewing screen. On unix systems this routine may    *
  248. * be invoked when X sends expose event to this program (see xgrphgen.c).     *
  249. *****************************************************************************/
  250. void UpdateInteractHandleInput(void)
  251. {
  252. #if !defined(__MSDOS__) && !defined(DJGCC)
  253.     GGClearViewArea();
  254. #endif /* !__MSDOS__ && !DJGCC */
  255.     if (LocalObjects)
  256.     ViewGeomObjectList(LocalObjects);
  257. }
  258.  
  259. /*****************************************************************************
  260. * A wrap to trap escapes in the drawing stage using long jump.             *
  261. *****************************************************************************/
  262. static void ViewGeomObjectList(IPObjectStruct *Objects)
  263. {
  264.     if (setjmp(LongJumpBuffer) == 0) {          /* Its the setjmp itself call! */
  265.     DrawAllObjects(Objects);
  266. #if !defined(__MSDOS__) && !defined(DJGCC)
  267.     GGGraphicFlush();
  268. #endif /* !__MSDOS__ && !DJGCC */
  269.     }
  270. }
  271.  
  272. /*****************************************************************************
  273. * Routine to save current view trans. IritPrsrViewMat to a generic mat file  *
  274. *****************************************************************************/
  275. static void SaveCurrentMat(void)
  276. {
  277.     int    i, j;
  278.     FILE *f;
  279.     char *p, FileName[PATH_NAME_LEN];
  280.     static char FileCount = '0';
  281.  
  282.     strcpy(FileName, GENERIC_MAT_FILE);
  283.     if ((p = strchr(FileName, '#')) != NULL) {
  284.     *p = FileCount;
  285.     if (FileCount++ == '9') FileCount = '0';
  286.     }
  287.     if ((f = fopen(FileName, "wt")) == NULL) {
  288.     GGTone(700, 200);
  289.     return;
  290.     }
  291.  
  292.     fprintf(f, "[OBJECT MATRICES\n    [OBJECT VIEW_MAT\n\t[MATRIX");
  293.     for (i = 0; i < 4; i++) {
  294.     fprintf(f, "\n\t    ");
  295.     for (j = 0; j < 4; j++) fprintf(f, "%12.9lf ", IritPrsrViewMat[i][j]);
  296.     }
  297.     fprintf(f, "\n\t]\n    ]\n");
  298.  
  299.     if (GlblViewMode == VIEW_PERSPECTIVE) {
  300.     fprintf(f, "    [OBJECT PRSP_MAT\n\t[MATRIX");
  301.     for (i = 0; i < 4; i++) {
  302.         fprintf(f, "\n\t    ");
  303.         for (j = 0; j < 4; j++) fprintf(f, "%12.9lf ", IritPrsrPrspMat[i][j]);
  304.     }
  305.     fprintf(f, "\n\t]\n    ]\n");
  306.     }
  307.  
  308.     fprintf(f, "]\n");
  309.  
  310.     fclose(f);
  311. }
  312.  
  313. /*****************************************************************************
  314. * Routine to draw all the objects in object list Objects.             *
  315. *****************************************************************************/
  316. void DrawAllObjects(IPObjectStruct *Objects)
  317. {
  318.     while (Objects) {
  319.     DrawOneObject(Objects);
  320.     Objects = Objects -> Pnext;
  321.     }
  322. }
  323.  
  324. /*****************************************************************************
  325. * Routine to draw one object Object.                         *
  326. *****************************************************************************/
  327. static void DrawOneObject(IPObjectStruct *PObject)
  328. {
  329.     IPPolygonStruct *PList;
  330.  
  331.     switch (PObject -> Type) {
  332.     case IP_OBJ_POLY:
  333.         PList = PObject -> U.PPolygon;
  334.             GGMySetColor(PObject -> Color);
  335.         while (PList) {
  336.             DrawOnePolygon(PList);
  337.             PList =    PList -> Pnext;
  338.         }
  339.         break;
  340.     case IP_OBJ_SURFACE:
  341. #ifdef __GL__
  342.         if (GlblDrawSolid) {
  343.         CagdSrfStruct *Srf;
  344.         IPObjectStruct *PPolyObj;
  345.         IPPolygonStruct *PPolygonTemp, *PPolygon;
  346.  
  347.         if (PObject -> FFPolygons == NULL) {
  348.             PObject -> FFPolygons = PPolyObj = IritPrsrNewObjectStruct();
  349.             *PPolyObj = *PObject;    /* Copy all its attributes. */
  350.             PPolyObj -> U.PPolygon = NULL;
  351.             PPolyObj -> Type = IP_OBJ_POLY;
  352.             for (Srf = PObject -> U.PSrfs;
  353.              Srf != NULL;
  354.              Srf = Srf -> Pnext) {
  355.             PPolygon = PPolygonTemp = Surface2Polygons(Srf);
  356.             while (PPolygonTemp -> Pnext)
  357.                 PPolygonTemp = PPolygonTemp -> Pnext;
  358.             PPolygonTemp -> Pnext = PPolyObj -> U.PPolygon;
  359.             PPolyObj -> U.PPolygon = PPolygon;
  360.             }
  361.         }
  362.  
  363.         DrawOneObject(PObject -> FFPolygons);
  364.         }
  365.         else
  366. #endif /* __GL__ */
  367.         DrawOneObject(PObject -> FFPolylines);
  368.         break;
  369.     case IP_OBJ_CURVE:
  370.         DrawOneObject(PObject -> FFPolylines);
  371.         break;
  372.     }
  373. }
  374.  
  375. /*****************************************************************************
  376. * Routine to draw one polygon, using global Matrix transform Mat.         *
  377. * Note this is the routine that    makes the real drawing...             *
  378. *****************************************************************************/
  379. static void DrawOnePolygon(IPPolygonStruct *PPolygon)
  380. {
  381.     int    i, j, DrawNextEdge, NumOfVertices;
  382.     RealType MappedNormal[3], PolyNormal[3];
  383.     IPVertexStruct
  384.     *VList = PPolygon -> PVertex,
  385.     *VHead = VList;
  386.  
  387.     if (VList == NULL) return;
  388.  
  389.     TestQuitView();
  390.  
  391.     switch (PPolygon -> Type) {
  392.     case IP_POINTLIST:
  393.         MoveToPtr(VList -> Coord);
  394.         DrawToPtr(VList -> Coord);
  395.         VList = VList -> Pnext;
  396.         for (i = 0;
  397.          i < GlblNumEdges && VList != NULL && VList != VHead;
  398.          i++) {
  399.         MoveToPtr(VList -> Coord);
  400.         DrawToPtr(VList -> Coord);
  401.         VList = VList -> Pnext;
  402.         }
  403.         break;
  404.     case IP_POLYLINE:
  405.         MoveToPtr(VList -> Coord);
  406.         DrawNextEdge = !IP_IS_VRTX_INTERNAL(VList);
  407.         VList = VList -> Pnext;
  408.         for (i = 1;
  409.          i < GlblNumEdges && VList != NULL && VList != VHead;
  410.          i++) {
  411.         if (DrawNextEdge || GlblInternal)
  412.             DrawToPtr(VList -> Coord);
  413.         else
  414.             MoveToPtr(VList -> Coord);
  415.  
  416.         DrawNextEdge = !IP_IS_VRTX_INTERNAL(VList);
  417.         VList = VList -> Pnext;
  418.         }
  419.         break;
  420.     case IP_POLYGON:
  421. #ifdef __GL__
  422.         if (GlblDrawSolid) {
  423.         DrawPolygonSolid(PPolygon);
  424.         break;
  425.         }
  426. #endif /* __GL__ */
  427.         if (GlblDrawPNormal && IP_HAS_POLY_PLANE(PPolygon)) {
  428.         /* Sum all points to be averaged for normal position. */
  429.         for (i = 0; i < 3; i++) PolyNormal[i] = VList -> Coord[i];
  430.         NumOfVertices = 1;
  431.         }
  432.  
  433.         MoveToPtr(VList -> Coord);
  434.         DrawNextEdge = !IP_IS_VRTX_INTERNAL(VList);
  435.         VList = VList -> Pnext;
  436.  
  437.         for (i = 1;
  438.          i < GlblNumEdges && VList != NULL;
  439.          i++) {
  440.         if (DrawNextEdge || GlblInternal)
  441.             DrawToPtr(VList -> Coord);
  442.         else
  443.             MoveToPtr(VList -> Coord);
  444.  
  445.         if (GlblDrawVNormal && IP_HAS_VRTX_NORMAL(VList)) {
  446.             for (j = 0; j < 3; j++) MappedNormal[j] =
  447.             VList -> Coord[j] + VList -> Normal[j] * GlblNormalLen;
  448.             j = GlblClosedObject;
  449.             GlblClosedObject = FALSE;
  450.             DrawToPtr(MappedNormal);
  451.             MoveToPtr(VList -> Coord);
  452.             GlblClosedObject = j;
  453.         }
  454.  
  455.         if (GlblDrawPNormal && IP_HAS_POLY_PLANE(PPolygon)) {
  456.             for (j = 0; j < 3; j++) PolyNormal[j] += VList -> Coord[j];
  457.             NumOfVertices++;
  458.         }
  459.  
  460.         DrawNextEdge = !IP_IS_VRTX_INTERNAL(VList);
  461.         VList = VList -> Pnext;
  462.         }
  463.  
  464.         if (GlblNumEdges > i) {
  465.         /* Close polygon by drawing a line to first vertex. */
  466.         if (DrawNextEdge || GlblInternal)
  467.             DrawToPtr(VHead -> Coord);
  468.         else
  469.             MoveToPtr(VHead -> Coord);
  470.  
  471.         if (GlblDrawVNormal && IP_HAS_VRTX_NORMAL(VList)) {
  472.             for (j = 0; j < 3; j++) MappedNormal[j] =
  473.             VList -> Coord[j] + VList -> Normal[j] * GlblNormalLen;
  474.             j = GlblClosedObject;
  475.             GlblClosedObject = FALSE;
  476.             DrawToPtr(MappedNormal);
  477.             MoveToPtr(VList -> Coord);
  478.             GlblClosedObject = j;
  479.         }
  480.         }
  481.  
  482.         if (GlblDrawPNormal && IP_HAS_POLY_PLANE(PPolygon)) {
  483.         for (i = 0; i < 3; i++) PolyNormal[i] /= NumOfVertices;
  484.         MoveToPtr(PolyNormal);
  485.         for (i = 0; i < 3; i++)
  486.                 PolyNormal[i] += PPolygon -> Plane[i] * GlblNormalLen;
  487.         i = GlblClosedObject;
  488.         GlblClosedObject = FALSE;
  489.         DrawToPtr(PolyNormal);
  490.         GlblClosedObject = i;
  491.         }
  492.         break;
  493.     }
  494. }
  495.  
  496. /*****************************************************************************
  497. *  Routine to test if quit display event - occured - SPACE was hit on         *
  498. * keyboard or right button was clicked on mouse.                 *
  499. *****************************************************************************/
  500. static void TestQuitView(void)
  501. {
  502.     if (GGIsAbortKeyPressed()) longjmp(LongJumpBuffer, 1);     /* Jump to... */
  503. }
  504.  
  505. /*****************************************************************************
  506. * Routine to mave to 3D    point given as Coord[3], using Mat transform.         *
  507. *****************************************************************************/
  508. void ScrnMoveTo(RealType Coords[3])
  509. {
  510.     MultVecby4by4(LastCoord, Coords, CrntViewMat);  /* Set last point coord. */
  511. }
  512.  
  513. /*****************************************************************************
  514. * Routine to draw to 3D    point given as Coord[3], using Mat transform, from   *
  515. * the last point we moved to.                             *
  516. *****************************************************************************/
  517. void ScrnDrawTo(RealType Coords[3])
  518. {
  519.     RealType NewCoord[3], MiddleCoord[3], t;
  520.  
  521.     MultVecby4by4(NewCoord, Coords, CrntViewMat);   /* Set last point coord. */
  522.     if (GlblClosedObject && NewCoord[2] < LastCoord[2]) {
  523.     GEN_COPY(LastCoord, NewCoord, 3 * sizeof(RealType));
  524.     return;
  525.     }
  526.  
  527.     /* Implementation of simple depth cue - if line is >Z or <Z ... */
  528.     if (LastCoord[2] <= 0.0 && NewCoord[2] <= 0.0) {    /* Draw the <Z part: */
  529.  
  530.     if (GlblDepthCue) GGMySetLineStyle(DOTTED_LINE);
  531.  
  532.     GGMyMove(LastCoord[0], LastCoord[1]);
  533.     GGMyDraw(NewCoord[0], NewCoord[1]);                /* DRAW! */
  534.     }
  535.     else if (LastCoord[2] >= 0.0 && NewCoord[2] >= 0.0 ||
  536.          ABS(LastCoord[2] - NewCoord[2]) < EPSILON) {
  537.     if (GlblDepthCue) GGMySetLineStyle(SOLID_LINE);
  538.  
  539.     GGMyMove(LastCoord[0], LastCoord[1]);
  540.     GGMyDraw(NewCoord[0], NewCoord[1]);                /* DRAW! */
  541.     }
  542.     else {                      /* Line intersect Z = 0 plane. */
  543.     t = LastCoord[2] / (LastCoord[2] - NewCoord[2]);
  544.     MiddleCoord[0] = LastCoord[0] * (1.0 - t) + NewCoord[0] * t;
  545.     MiddleCoord[1] = LastCoord[1] * (1.0 - t) + NewCoord[1] * t;
  546.  
  547.     if (GlblDepthCue) GGMySetLineStyle(SOLID_LINE);
  548.  
  549.     if (LastCoord[2] > 0.0) {
  550.         GGMyMove(LastCoord[0], LastCoord[1]);
  551.         GGMyDraw(MiddleCoord[0], MiddleCoord[1]);            /* DRAW! */
  552.     }
  553.     else {
  554.         GGMyMove(MiddleCoord[0], MiddleCoord[1]);
  555.         GGMyDraw(NewCoord[0], NewCoord[1]);                /* DRAW! */
  556.     }
  557.  
  558.     if (GlblDepthCue) GGMySetLineStyle(DOTTED_LINE);/* Draw the <Z part: */
  559.  
  560.     if (LastCoord[2] < 0.0) {
  561.         GGMyMove(LastCoord[0], LastCoord[1]);
  562.         GGMyDraw(MiddleCoord[0], MiddleCoord[1]);            /* DRAW! */
  563.     }
  564.     else {
  565.         GGMyMove(MiddleCoord[0], MiddleCoord[1]);
  566.         GGMyDraw(NewCoord[0], NewCoord[1]);                /* DRAW! */
  567.     }
  568.     }
  569.  
  570.     GEN_COPY(LastCoord, NewCoord, 3 * sizeof(RealType));  /* Set crnt point. */
  571. }
  572.  
  573. #ifdef __GL__
  574.  
  575. /****************************************************************************
  576. * Routine to draw a polygon full.                        *
  577. * This routine should be supplied only if GL is linked in.            *
  578. ****************************************************************************/
  579. static void DrawPolygonSolid(IPPolygonStruct *PPolygon)
  580. {
  581.     int i,
  582.     l = 0,
  583.     UseVertexNormal = FALSE;
  584.     float *PolygonNormal, FloatNormal[3], Length;
  585.     RealType Normal[3], MappedVertex[3], V1[3], V2[3], V3[3];
  586.     IPVertexStruct
  587.     *VList = PPolygon -> PVertex;
  588.  
  589.     if (IP_HAS_VRTX_NORMAL(VList))
  590.     UseVertexNormal = TRUE;
  591.     else if (!IP_HAS_POLY_PLANE(PPolygon)) {
  592.     /* Compute normal to polygon by cross prod. of 3 consecutive points. */
  593.     MultVecby4by4(V1, VList -> Coord, IritPrsrViewMat);
  594.     MultVecby4by4(V2, VList -> Pnext-> Coord, IritPrsrViewMat);
  595.     MultVecby4by4(V3, VList -> Pnext -> Pnext -> Coord, IritPrsrViewMat);
  596.     for (i = 0; i < 3; i++) V1[i] -= V2[i];
  597.     for (i = 0; i < 3; i++) V2[i] -= V3[i];
  598.     Normal[0] = V1[1] * V2[2] - V1[2] * V2[1];
  599.     Normal[1] = V1[2] * V2[0] - V1[0] * V2[2];
  600.     Normal[2] = V1[0] * V2[1] - V1[1] * V2[0];
  601.     Length = sqrt(SQR(Normal[0]) + SQR(Normal[1]) + SQR(Normal[2]));
  602.     for (i = 0; i < 3; i++) Normal[i] /= -Length;
  603.     }
  604.     else {
  605.     for (i = 0; i < 3; i++)
  606.         Normal[i] = VList -> Coord[i] + PPolygon -> Plane[i];
  607.     MultVecby4by4(V1, VList -> Coord, IritPrsrViewMat);
  608.     MultVecby4by4(V2, Normal, IritPrsrViewMat);
  609.     for (i = 0; i < 3; i++) Normal[i] = V2[i] - V1[i];
  610.     Length = sqrt(SQR(Normal[0]) + SQR(Normal[1]) + SQR(Normal[2]));
  611.     for (i = 0; i < 3; i++) Normal[i] /= -Length;
  612.     }
  613.  
  614.     GGMyDrawPolygonSolid(NULL, NULL, TRUE);
  615.  
  616.     for (; VList != NULL; VList = VList -> Pnext) {
  617.     MultVecby4by4(MappedVertex, VList -> Coord, CrntViewMat);
  618.  
  619.     /* Each vertex has different normal - specify them. */
  620.     if (UseVertexNormal) {
  621.         MultVecby4by4(V1, VList -> Coord, IritPrsrViewMat);
  622.         for (i = 0; i < 3; i++)
  623.         Normal[i] = VList -> Coord[i] + VList -> Normal[i];
  624.         MultVecby4by4(V2, Normal, IritPrsrViewMat);
  625.         for (i = 0; i < 3; i++) Normal[i] = V2[i] - V1[i];
  626.         Length = sqrt(SQR(Normal[0]) + SQR(Normal[1]) + SQR(Normal[2]));
  627.         for (i = 0; i < 3; i++) Normal[i] /= -Length;
  628.     }
  629.  
  630.     for (i = 0; i < 3; i++) FloatNormal[i] = Normal[i];
  631.  
  632.     GGMyDrawPolygonSolid(MappedVertex, FloatNormal, TRUE);
  633.  
  634.     if (l >= 255) break;                        /* GL limit. */
  635.     }
  636.  
  637.     GGMyDrawPolygonSolid(NULL, NULL, FALSE);
  638. }
  639.  
  640. #endif /* __GL__ */
  641.  
  642.